package com.softdev.system.generator.controller;

import com.softdev.system.generator.entity.ClassInfo;
import com.softdev.system.generator.entity.ReturnT;
import com.softdev.system.generator.util.CodeGeneratorTool;
import com.softdev.system.generator.util.FreemarkerTool;
import freemarker.template.TemplateException;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * spring boot code generator
 *
 * @author zhengk/moshow
 */
@Controller
@Slf4j
public class IndexController {

    @Autowired
    private FreemarkerTool freemarkerTool;

    @GetMapping("/")
    public String index() {
        return "index";
    }

    @PostMapping("/genCode")
    @ResponseBody
    public ReturnT<Map<String, String>> codeGenerate(String tableSql,
                                                     //2019-2-10 liutf 修改为@RequestParam参数校验
                                                     @RequestParam(required = false, defaultValue = "zengyan") String authorName,
                                                     @RequestParam(required = false, defaultValue = "com.cqfae.pmo.zhcz.bgt") String packageName,
                                                     @RequestParam(required = false, defaultValue = "Bgt") String returnUtil
    ) {


        try {

            if (StringUtils.isBlank(tableSql)) {
                return new ReturnT<>(ReturnT.FAIL_CODE, "表结构信息不可为空");
            }

            // parse table
            ClassInfo classInfo = CodeGeneratorTool.processTableIntoClassInfo(tableSql);

            // code genarete
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("classInfo", classInfo);
            params.put("authorName", authorName);
            params.put("packageName", packageName);
            params.put("returnUtil", returnUtil);

            // result
            Map<String, String> result = new HashMap<String, String>();

            //ysy
            result.put("ysy_Do", freemarkerTool.processString("code-generator/ysy/Do.ftl", params));
            result.put("ysy_Form", freemarkerTool.processString("code-generator/ysy/Form.ftl", params));
            result.put("ysy_ListForm", freemarkerTool.processString("code-generator/ysy/ListForm.ftl", params));
            result.put("ysy_PageForm", freemarkerTool.processString("code-generator/ysy/PageForm.ftl", params));
            result.put("ysy_Dto", freemarkerTool.processString("code-generator/ysy/Dto.ftl", params));
            result.put("ysy_mybatis", freemarkerTool.processString("code-generator/ysy/mybatis.ftl", params));
            result.put("ysy_Dao", freemarkerTool.processString("code-generator/ysy/Dao.ftl", params));
            result.put("ysy_Service", freemarkerTool.processString("code-generator/ysy/service.ftl", params));
            result.put("ysy_ServiceImpl", freemarkerTool.processString("code-generator/ysy/serviceImpl.ftl", params));
            result.put("ysy_Controller", freemarkerTool.processString("code-generator/ysy/Controller.ftl", params));





            // 计算,生成代码行数
            int lineNum = 0;
            for (Map.Entry<String, String> item : result.entrySet()) {
                if (item.getValue() != null) {
                    lineNum += StringUtils.countMatches(item.getValue(), "\n");
                }
            }
            log.info("生成代码行数：{}", lineNum);
            //测试环境可自行开启
            //log.info("生成代码数据：{}", result);
            return new ReturnT<>(result);
        } catch (IOException | TemplateException e) {
            log.error(e.getMessage(), e);
            return new ReturnT<>(ReturnT.FAIL_CODE, "表结构解析失败" + e.getMessage());
        }
    }

    /**
     * 输入表名和字段名生成建表语句(暂只支持 postgresql )
     * TODO 支持生成mysql建表语句
     *
     * @param tableName 表名
     * @param fields    字段名
     * @param comments  注释
     * @param types     数据类型
     * @param lengths   数据项长度
     * @return sql 语句
     */
    @GetMapping("/sqlGenerate")
    @ResponseBody
    @ApiOperation("输入表名和字段名生成建表语句")
    public String sqlGenerate(@RequestParam String tableName, String fields, String comments, String types, String lengths, String explanations) {
        tableName = "t_" + tableName.toLowerCase();

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("DROP TABLE IF EXISTS \"public\".\"").append(tableName).append("\";\n");
        stringBuilder.append("CREATE TABLE \"public\".\"").append(tableName).append("\" (\n").append("\"id\" varchar(255) NOT NULL,\n");

        String[] fieldsArr = null;
        String[] commentsArr = null;
        String[] lengthsArr = null;
        String[] typesArr = null;
        String[] explanationsArr = null;

        // 字段
        if (StringUtils.isNotBlank(fields)) {
            if (fields.contains(" ")) {
                fieldsArr = fields.split(" ");
            } else {
                fieldsArr = fields.split(",");
            }
        }

        // 类型
        if (StringUtils.isNotBlank(types)) {
            if (types.contains(" ")) {
                typesArr = types.split(" ");
            } else {
                typesArr = types.split(",");
            }
        }

        // 注释
        if (StringUtils.isNotBlank(comments)) {
            if (comments.contains(" ")) {
                commentsArr = comments.split(" ");
            } else {
                commentsArr = comments.split(",");
            }
        }

        // 长度
        if (StringUtils.isNotBlank(lengths)) {
            if (lengths.contains(" ")) {
                lengthsArr = lengths.split(" ");
            } else {
                lengthsArr = lengths.split(",");
            }
        }

        if (StringUtils.isNotBlank(explanations)) {
            explanationsArr = explanations.split(" ");
        }

        for (int i = 0; i < fieldsArr.length; i++) {
            if ("id".equals(fieldsArr[i].toLowerCase())) {
                continue;
            }

            if (typesArr != null) {
                if (lengthsArr != null) {
                    if (StringUtils.isNotBlank(typesArr[i]) && StringUtils.isNotBlank(lengthsArr[i])) {
                        String type = conversionType(typesArr[i]);
                        if (fieldsArr[i].toLowerCase().endsWith("_time")) {
                            stringBuilder.append("\"").append(fieldsArr[i].toLowerCase()).append("\"").append(" timestamp(6),\n");
                        } else {
                            if ("int4".equals(type)) {
                                stringBuilder.append("\"").append(fieldsArr[i].toLowerCase()).append("\"").append(" " + type + ",\n");
                            } else {
                                stringBuilder.append("\"").append(fieldsArr[i].toLowerCase()).append("\"").append(" " + type + "(" + lengthsArr[i] + "),\n");
                            }
                        }
                    }
                } else {
                    if (fieldsArr[i].toLowerCase().endsWith("_time")) {
                        stringBuilder.append("\"").append(fieldsArr[i].toLowerCase()).append("\"").append(" timestamp(6),\n");
                    } else {
                        stringBuilder.append("\"").append(fieldsArr[i].toLowerCase()).append("\"").append(" varchar(").append(lengthsArr[i]).append("),\n");
                    }
                }
            } else {
                if (fieldsArr[i].toLowerCase().endsWith("_time")) {
                    stringBuilder.append("\"").append(fieldsArr[i].toLowerCase()).append("\"").append(" timestamp(6),\n");
                } else {
                    stringBuilder.append("\"").append(fieldsArr[i].toLowerCase()).append("\"").append(" varchar(255),\n");
                }
            }
        }

        stringBuilder.append("CONSTRAINT ").append("\"").append(tableName).append("_pkey").append("\"").append(" PRIMARY KEY (\"id\")\n" +
                ");\n");

        stringBuilder.append("ALTER TABLE \"public\".\"").append(tableName).append("\"\n").append("OWNER TO \"postgres\";\n");

        for (int i = 0; i < fieldsArr.length; i++) {
            if (commentsArr != null && commentsArr[i] != null) {
                if (explanationsArr != null && explanationsArr[i] != null) {
                    stringBuilder.append("COMMENT ON COLUMN \"public\".\"").append(tableName).append("\".\"").append(fieldsArr[i].toLowerCase()).append("\" IS '").append(commentsArr[i]).append(" ").append(explanationsArr[i]).append("';\n");
                } else {
                    stringBuilder.append("COMMENT ON COLUMN \"public\".\"").append(tableName).append("\".\"").append(fieldsArr[i].toLowerCase()).append("\" IS '").append(commentsArr[i]).append("';\n");
                }
            }
        }

        return stringBuilder.toString();
    }

    /**
     * 转换数据类型
     *
     * @param typeAbbreviation
     * @return
     */
    public String conversionType(String typeAbbreviation) {
        if ("C".equals(typeAbbreviation)) {
            return "varchar";
        } else if ("N".equals(typeAbbreviation)) {
            return "int4";
        }
        return null;
    }

}
